package com.brandon.HuntedRPG.model.listeners;

import java.lang.ref.WeakReference;
import java.util.ArrayList;

import com.brandon.HuntedRPG.HuntedRPGApplication;

public class ListOfListeners<T> {
	private final ArrayList<WeakReference<T>> listeners = new ArrayList<WeakReference<T>>();
	
	public void add(T listener) {
		if (HuntedRPGApplication.DEVELOPMENT_VALIDATEDATA) {
			for (WeakReference<T> ref : listeners) {
				if (ref.get() == listener) {
					throw new IndexOutOfBoundsException("FAIL: listener added twice to ListOfListeners.");
				}
			}
		}
		listeners.add(new WeakReference<T>(listener));
	}
	public void remove(T listenerToRemove) {
		for (int i = listeners.size()-1; i >= 0; --i) {
			T listener = listeners.get(i).get();
			if (listener == null || listener == listenerToRemove) {
				listeners.remove(i);
			}
		}
	}
	
	protected void callAllListeners(Function<T> e) {
		for (int i = listeners.size()-1; i >= 0; --i) {
			T listener = listeners.get(i).get();
			if (listener == null) listeners.remove(i);
			else e.call(listener);
		}
	}
	protected <Arg1> void callAllListeners(Function1<T, Arg1> e, Arg1 arg) {
		for (int i = listeners.size()-1; i >= 0; --i) {
			T listener = listeners.get(i).get();
			if (listener == null) listeners.remove(i);
			else e.call(listener, arg);
		}
	}
	protected <Arg1, Arg2> void callAllListeners(Function2<T, Arg1, Arg2> e, Arg1 arg1, Arg2 arg2) {
		for (int i = listeners.size()-1; i >= 0; --i) {
			T listener = listeners.get(i).get();
			if (listener == null) listeners.remove(i);
			else e.call(listener, arg1, arg2);
		}
	}
	
	protected static interface Function<Listener> {
		public void call(Listener listener);
	}
	protected static interface Function1<Listener, Arg1> {
		public void call(Listener listener, Arg1 arg1);
	}
	protected static interface Function2<Listener, Arg1, Arg2> {
		public void call(Listener listener, Arg1 arg1, Arg2 arg2);
	}
}